/**
 * XL-Request 智能网络请求管理器
 * 提供自动重试、请求队列、全局Loading和错误处理、RESTful和GraphQL支持
 */
import RequestQueue from './request-queue';
import { RequestConfig } from './types';
import { RestfulAdapter } from './adapters/restful';
import { GraphQLAdapter } from './adapters/graphql';
import store from './store';

class XlRequest {
  constructor(config = {}) {
    this.config = {
      baseURL: '',
      timeout: 60000,
      headers: {
        'Content-Type': 'application/json',
      },
      retry: {
        maxRetries: 3,
        retryDelay: 1000,
        retryableStatusCodes: [408, 500, 502, 503, 504]
      },
      queue: {
        maxConcurrent: 6,
        priorityLevels: 3
      },
      loading: {
        global: true,
        delay: 300,
        customLoading: null
      },
      errorHandler: null,
      validateStatus: (status) => status >= 200 && status < 300,
      ...config
    };

    // 初始化请求队列
    this.queue = new RequestQueue({
      maxConcurrent: this.config.queue.maxConcurrent,
      priorityLevels: this.config.queue.priorityLevels
    });

    // 初始化适配器
    this.restAdapter = new RestfulAdapter(this.config);
    this.graphqlAdapter = new GraphQLAdapter({
      ...this.config,
      headers: {
        ...this.config.headers,
        'Content-Type': 'application/json',
      }
    });

    // 初始化存储
    this.store = store;

    // 创建请求拦截器
    this.interceptors = {
      request: [],
      response: [],
      error: [],
    };
    
    // 活跃请求映射
    this.activeRequests = new Map();
  }

  /**
   * 设置全局配置
   * @param {Object} config 配置对象
   */
  setConfig(config = {}) {
    this.config = { ...this.config, ...config };
    
    // 更新适配器配置
    this.restAdapter.setConfig(this.config);
    this.graphqlAdapter.setConfig(this.config);
    
    // 更新队列配置
    if (config.queue) {
      this.queue.setConfig({
        maxConcurrent: config.queue.maxConcurrent,
        priorityLevels: config.queue.priorityLevels,
      });
    }
    
    return this;
  }

  /**
   * 设置全局请求头
   * @param {Object} headers 请求头对象
   */
  setHeaders(headers = {}) {
    this.config.headers = { ...this.config.headers, ...headers };
    this.restAdapter.setConfig({ headers: this.config.headers });
    this.graphqlAdapter.setConfig({ headers: this.config.headers });
    return this;
  }

  /**
   * 添加请求中间件
   * @param {Object} middleware 中间件对象
   */
  use(middleware = {}) {
    if (middleware.beforeRequest && typeof middleware.beforeRequest === 'function') {
      this.interceptors.request.push(middleware.beforeRequest);
    }
    
    if (middleware.afterResponse && typeof middleware.afterResponse === 'function') {
      this.interceptors.response.push(middleware.afterResponse);
    }
    
    if (middleware.onError && typeof middleware.onError === 'function') {
      this.interceptors.error.push(middleware.onError);
    }
    
    return this;
  }
  
  /**
   * 执行请求前拦截器
   * @param {Object} config 请求配置
   * @returns {Object} 修改后的请求配置
   */
  async _runRequestInterceptors(config) {
    let currentConfig = { ...config };
    
    for (const interceptor of this.interceptors.request) {
      try {
        const result = await interceptor(currentConfig);
        if (result) {
          currentConfig = result;
        }
      } catch (error) {
        throw error;
      }
    }
    
    return currentConfig;
  }
  
  /**
   * 执行响应拦截器
   * @param {Object} response 响应对象
   * @returns {Object} 修改后的响应
   */
  async _runResponseInterceptors(response) {
    let currentResponse = response;
    
    for (const interceptor of this.interceptors.response) {
      try {
        const result = await interceptor(currentResponse);
        if (result) {
          currentResponse = result;
        }
      } catch (error) {
        throw error;
      }
    }
    
    return currentResponse;
  }
  
  /**
   * 执行错误拦截器
   * @param {Error} error 错误对象
   * @param {Object} config 请求配置
   */
  async _runErrorInterceptors(error, config) {
    let currentError = error;
    
    // 先运行自定义拦截器
    for (const interceptor of this.interceptors.error) {
      try {
        const result = await interceptor(currentError, config);
        if (result instanceof Error) {
          currentError = result;
        } else if (result) {
          // 如果返回非错误值，则中断错误链并返回该值
          return result;
        }
      } catch (interceptorError) {
        currentError = interceptorError;
      }
    }
    
    // 然后运行全局错误处理器（如果存在）
    if (this.config.errorHandler && typeof this.config.errorHandler === 'function') {
      try {
        return await this.config.errorHandler(currentError, config);
      } catch (handlerError) {
        throw handlerError;
      }
    }
    
    // 如果没有处理器处理错误，则抛出错误
    throw currentError;
  }

  /**
   * 发送请求
   * @param {Object} userConfig 请求配置
   * @returns {Promise} 请求结果
   */
  async request(userConfig) {
    // 合并配置
    const config = {
      ...this.config,
      ...userConfig,
      headers: {
        ...this.config.headers,
        ...(userConfig.headers || {}),
      },
    };
    
    // 处理请求ID
    const requestId = config.requestId || `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    config.requestId = requestId;
    
    // 处理请求优先级
    const priority = typeof config.priority === 'number' ? 
      Math.min(Math.max(config.priority, 0), this.config.queue.priorityLevels - 1) : 
      1; // 默认中等优先级
    
    // 设置loading状态
    if (config.loading !== false) {
      this._showLoading(config);
    }
    
    // 创建任务
    const task = async () => {
      try {
        // 运行请求拦截器
        const processedConfig = await this._runRequestInterceptors(config);
        
        // 根据请求类型选择适配器
        let response;
        if (processedConfig._isGraphQL) {
          response = await this.graphqlAdapter.request(processedConfig);
        } else {
          response = await this.restAdapter.request(processedConfig);
        }
        
        // 运行响应拦截器
        const processedResponse = await this._runResponseInterceptors(response);
        
        // 更新统计信息
        this._updateStats(true, processedConfig);
        
        // 处理loading
        this._hideLoading(processedConfig);
        
        // 清理活跃请求
        this._removeActiveRequest(requestId);
        
        return processedResponse;
      } catch (error) {
        // 检查是否需要重试
        if (this._shouldRetry(error, config)) {
          return await this._retryRequest(config);
        }
        
        // 更新统计信息
        this._updateStats(false, config);
        
        // 处理loading
        this._hideLoading(config);
        
        // 清理活跃请求
        this._removeActiveRequest(requestId);
        
        // 更新错误状态
        this._updateErrorState(error, config);
        
        // 运行错误拦截器
        return await this._runErrorInterceptors(error, config);
      }
    };
    
    // 添加到活跃请求
    this._addActiveRequest(requestId, config);
    
    // 将任务添加到队列
    return this.queue.add(task, { priority, requestId });
  }
  
  /**
   * 发送GET请求
   * @param {String} url 请求URL
   * @param {Object} params URL参数
   * @param {Object} config 请求配置
   * @returns {Promise} 请求结果
   */
  get(url, params = {}, config = {}) {
    return this.request({
      ...config,
      url,
      method: 'GET',
      params,
    });
  }
  
  /**
   * 发送POST请求
   * @param {String} url 请求URL
   * @param {Object} data 请求数据
   * @param {Object} config 请求配置
   * @returns {Promise} 请求结果
   */
  post(url, data = {}, config = {}) {
    return this.request({
      ...config,
      url,
      method: 'POST',
      data,
    });
  }
  
  /**
   * 发送PUT请求
   * @param {String} url 请求URL
   * @param {Object} data 请求数据
   * @param {Object} config 请求配置
   * @returns {Promise} 请求结果
   */
  put(url, data = {}, config = {}) {
    return this.request({
      ...config,
      url,
      method: 'PUT',
      data,
    });
  }
  
  /**
   * 发送DELETE请求
   * @param {String} url 请求URL
   * @param {Object} config 请求配置
   * @returns {Promise} 请求结果
   */
  delete(url, config = {}) {
    return this.request({
      ...config,
      url,
      method: 'DELETE',
    });
  }
  
  /**
   * 发送GraphQL请求
   * @param {Object} options GraphQL选项
   * @returns {Promise} 请求结果
   */
  graphql(options) {
    return this.request({
      ...options,
      _isGraphQL: true,
    });
  }
  
  /**
   * 取消请求
   * @param {String} requestId 请求ID
   */
  cancel(requestId) {
    if (this.activeRequests.has(requestId)) {
      const request = this.activeRequests.get(requestId);
      if (request && request.controller) {
        request.controller.abort();
        this._removeActiveRequest(requestId);
      }
    }
    
    // 从队列中移除
    this.queue.remove(requestId);
  }
  
  /**
   * 取消所有请求
   * @param {String} reason 取消原因
   */
  cancelAll(reason = 'Request cancelled by user') {
    // 取消所有活跃请求
    this.activeRequests.forEach((request, requestId) => {
      if (request && request.controller) {
        request.controller.abort(reason);
      }
    });
    
    // 清空活跃请求映射
    this.activeRequests.clear();
    
    // 清空队列
    this.queue.clear();
    
    // 重置loading状态
    this.store.setLoading(false);
  }
  
  /**
   * 添加活跃请求
   * @param {String} requestId 请求ID
   * @param {Object} config 请求配置
   */
  _addActiveRequest(requestId, config) {
    // 创建AbortController
    const controller = new AbortController();
    
    // 保存到活跃请求映射
    this.activeRequests.set(requestId, {
      controller,
      config,
      timestamp: Date.now(),
    });
    
    // 更新store中的活跃请求
    this.store.addActiveRequest({
      id: requestId,
      url: config.url,
      method: config.method || 'GET',
      timestamp: Date.now(),
    });
  }
  
  /**
   * 移除活跃请求
   * @param {String} requestId 请求ID
   */
  _removeActiveRequest(requestId) {
    this.activeRequests.delete(requestId);
    this.store.removeActiveRequest(requestId);
  }
  
  /**
   * 显示加载状态
   * @param {Object} config 请求配置
   */
  _showLoading(config) {
    const shouldShowGlobal = config.loading !== false && 
      this.config.loading.global !== false;
    
    if (shouldShowGlobal) {
      // 使用延迟防止闪烁
      const delay = config.loadingDelay || this.config.loading.delay || 0;
      
      setTimeout(() => {
        // 如果请求仍在活跃中，则显示loading
        if (this.activeRequests.has(config.requestId)) {
          this.store.setLoading(true);
          
          // 如果有自定义loading实现，则调用它
          if (typeof this.config.loading.customLoading === 'function') {
            this.config.loading.customLoading(true, config);
          }
        }
      }, delay);
    }
  }
  
  /**
   * 隐藏加载状态
   * @param {Object} config 请求配置
   */
  _hideLoading(config) {
    const shouldShowGlobal = config.loading !== false && 
      this.config.loading.global !== false;
    
    if (shouldShowGlobal) {
      // 检查是否还有其他活跃请求
      const hasActiveRequests = this.activeRequests.size > 0;
      
      if (!hasActiveRequests) {
        this.store.setLoading(false);
        
        // 如果有自定义loading实现，则调用它
        if (typeof this.config.loading.customLoading === 'function') {
          this.config.loading.customLoading(false, config);
        }
      }
    }
  }
  
  /**
   * 更新请求统计信息
   * @param {Boolean} success 是否成功
   * @param {Object} config 请求配置
   */
  _updateStats(success, config) {
    this.store.updateStats({
      total: 1,
      success: success ? 1 : 0,
      error: success ? 0 : 1,
      method: config.method || 'GET',
    });
  }
  
  /**
   * 更新错误状态
   * @param {Error} error 错误对象
   * @param {Object} config 请求配置
   */
  _updateErrorState(error, config) {
    // 构建错误状态对象
    const errorStatus = {
      url: config.url,
      method: config.method || 'GET',
      status: error.status || error.statusCode || 0,
      message: error.message || 'Unknown error',
      timestamp: Date.now(),
    };
    
    // 更新错误状态
    this.store.setError(errorStatus);
    
    // 添加到错误历史
    this.store.addErrorHistory(errorStatus);
  }
  
  /**
   * 判断是否应该重试请求
   * @param {Error} error 错误对象
   * @param {Object} config 请求配置
   * @returns {Boolean} 是否应该重试
   */
  _shouldRetry(error, config) {
    // 如果当前重试次数已达到最大值，则不再重试
    const currentRetryCount = config._retryCount || 0;
    const maxRetries = config.retry?.maxRetries ?? this.config.retry.maxRetries;
    
    if (currentRetryCount >= maxRetries) {
      return false;
    }
    
    // 如果请求被取消，则不再重试
    if (error.name === 'AbortError') {
      return false;
    }
    
    // 检查状态码是否在可重试列表中
    const status = error.status || error.statusCode || 0;
    const retryableStatusCodes = config.retry?.retryableStatusCodes ?? 
      this.config.retry.retryableStatusCodes;
    
    if (status > 0 && !retryableStatusCodes.includes(status)) {
      return false;
    }
    
    // 网络错误和超时错误可以重试
    const isNetworkError = !status || status === 0;
    const isTimeoutError = error.code === 'ECONNABORTED' || 
      error.message?.toLowerCase().includes('timeout');
    
    return isNetworkError || isTimeoutError || retryableStatusCodes.includes(status);
  }
  
  /**
   * 重试请求
   * @param {Object} config 请求配置
   * @returns {Promise} 请求结果
   */
  async _retryRequest(config) {
    const currentRetryCount = config._retryCount || 0;
    const retryConfig = {
      ...config,
      _retryCount: currentRetryCount + 1,
    };
    
    // 计算延迟时间
    const delay = config.retry?.retryDelay ?? this.config.retry.retryDelay;
    const retryDelay = typeof delay === 'function' ? 
      delay(currentRetryCount) : 
      delay;
    
    // 等待后重试
    await new Promise(resolve => setTimeout(resolve, retryDelay));
    
    // 重新发送请求
    return this.request(retryConfig);
  }
}

// 创建默认实例
const defaultInstance = new XlRequest();

// 导出默认实例和类
export default defaultInstance;
export { XlRequest }; 